package com.aigc.sclassroom.service.impl;

import com.aigc.sclassroom.mapper.*;
import com.aigc.sclassroom.pojo.Sign;
import com.aigc.sclassroom.pojo.SignRecord;
import com.aigc.sclassroom.pojo.Team;
import com.aigc.sclassroom.service.SignService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.messaging.simp.SimpMessagingTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;

import java.security.SecureRandom;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

@Service
public class SignServiceImpl implements SignService {

    private static final Logger logger = LoggerFactory.getLogger(SignServiceImpl.class);
    @Autowired
    private SignMapper signMapper;

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private SignRecordMapper recordMapper;

    @Autowired
    private TeamMapper teamMapper; // 假设TeamMapper已存在

    @Autowired
    private ClassMapper classMapper;

    @Autowired
    private SimpMessagingTemplate messagingTemplate;

 /*   public SignServiceImpl(SignRecordMapper recordMapper) {
        this.recordMapper = recordMapper;
    }*/

    @Override
    // 教师发起签到
    @Transactional
    public Sign createSign(Long classId, Integer duration) {
        // 检查是否存在重复的签到记录
        Integer count = signMapper.selectCountByClassId(classId);
//        if (count >= 3) {
//            logger.error("每节课最多签到三次");
//            throw new RuntimeException("每节课最多签到三次");
//        }
        Sign sign = new Sign();
        sign.setClassId(classId);
        sign.setSignCode(generateRandomCode());
        sign.setStartTime(LocalDateTime.now());
        sign.setEndTime(LocalDateTime.now().plusMinutes(duration));
        sign.setDuration(duration);
        sign.setSignOrder(count + 1);
        signMapper.insertSign(sign);
        logger.info("签到创建成功，签到ID: {}", sign.getSignId());
        return sign;
    }
    /**
     * 学生签到方法
     *
     * @param signId 签到活动的ID
     * @param userId 学生的用户ID
     * @param code   签到验证码
     * @throws RuntimeException 当签到不存在、签到码错误、签到已结束或学生已签到时会抛出此异常
     */

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void studentSign(Long signId, Long userId, String code,Long courseManageId) {
        // 通过验证pinia的courseManageId学生是否属于该课程
        List<Team> teams = teamMapper.findTeamByCourseManageId(courseManageId);
        boolean isCourseStudent = false;
        for (Team team : teams) {
            if (team.getTeamUserId().equals(userId)) {
                isCourseStudent = true;
                break;
            }
        }
        if (!isCourseStudent) {
            logger.error("该学生不属于该课程，无法签到，学生ID: {}", userId);
            throw new RuntimeException("该学生不属于该课程，无法签到");
        }
        // 通过验证pinia的signId学生是否属于该课程
        Long classId = signMapper.getClassIdBySignId(signId);
        Long courseManageId2 = classMapper.getCourseManageIdByClass(classId);
        List<Team> teams2 = teamMapper.findTeamByCourseManageId(courseManageId2);
        boolean isCourseStudent2 = false;
        for (Team team : teams2) {
            if (team.getTeamUserId().equals(userId)) {
                isCourseStudent2 = true;
                break;
            }
        }
        if (!isCourseStudent2) {
            logger.error("该学生不属于该课程，无法签到，学生ID: {}", userId);
            throw new RuntimeException("该学生不属于该课程，无法签到");
        }

        try {
            Sign sign = signMapper.selectById(signId);
            if (sign == null) {
                throw new RuntimeException("签到不存在");
            }
            if (!sign.getSignCode().equals(code)) {
                throw new RuntimeException("签到码错误");
            }
            if (LocalDateTime.now().isAfter(sign.getEndTime())) {
                throw new RuntimeException("签到已结束");
            }
            // 检查该学生是否已经有签到记录
            Integer count = recordMapper.checkSigned(signId, userId);
            if (count > 0) {
                throw new RuntimeException("请勿重复签到");
            }
            // 创建新的签到记录
            SignRecord record = new SignRecord();
            record.setSignId(signId);
            record.setUserId(userId);
            record.setStatus(1);
            record.setSignTime(LocalDateTime.now());
            recordMapper.insertRecord(record);
            // 推送实时数据
            // messagingTemplate.convertAndSend("/topic/sign/" + signId, getSignStatus(signId));
        } catch (Exception e) {
            logger.error("Error occurred during student sign", e);
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            throw e;
        }
    }

    // 生成6位随机码
    private String generateRandomCode() {
        return String.format("%06d", new Random().nextInt(999999));
    }

    @Override
    public Map<String, Object> getSignStatus(Long signId) {
        List<SignRecord> records = recordMapper.selectBySignId(signId);
        long signedCount = records.stream().filter(r -> r.getStatus() == 1).count();
        Long classId = signMapper.getClassIdBySignId(signId);
        Long courseManageId = classMapper.getCourseManageIdByClass(classId);
        // 获取该课程的所有学生
        List<Team> teams = teamMapper.findTeamByCourseManageId(courseManageId);
        int total = teams.size();
        // 获取已签到学生的用户ID
        Set<Long> signedUserIds = records.stream()
                .filter(r -> r.getStatus() == 1)
                .map(SignRecord::getUserId)
                .collect(Collectors.toSet());

        // 统计未签到的学生数量
        long total2 = teams.stream()
                .filter(team -> !signedUserIds.contains(team.getTeamUserId()))
                .count();

        // 找出未签到的学生，仅添加用户名不为 null 的学生
        List<String> unSignedStudents = teams.stream()
                .filter(team -> !signedUserIds.contains(team.getTeamUserId()))
                .map(team -> userMapper.getUsernNameById(team.getTeamUserId()))
                .filter(Objects::nonNull)
                .collect(Collectors.toList());

        // 构建包含用户名的学生签到状态列表
        List<Map<String, Object>> students = records.stream()
                .map(r -> {
                    String username = userMapper.getUsernNameById(r.getUserId());
                    Map<String, Object> studentMap = new HashMap<>();
                    studentMap.put("username", username);
                    studentMap.put("status", r.getStatus());
                    return studentMap;
                })
                .collect(Collectors.toList());

        // 计算签到率，使用 double 类型进行精确计算
        double rate = total > 0 ? (double) signedCount * 100 / total : 0;
        // 使用 String.format 保留1位小数
        String signInRate = String.format("%.1f", rate);

        // 显式指定最终返回的 Map 的值类型为 Object
        Map<String, Object> result = new HashMap<>();
        result.put("signed", signedCount);
        result.put("total", total);
        result.put("signInRate", signInRate);
        result.put("students", students);
        result.put("total2",total2);
        result.put("unSignedStudents", unSignedStudents);
        return result;
    }

    @Override
    public Map<String, Object> getStatistics(Long courseManageId) {
        // 获取课程下的所有 classId
        List<Long> classIdList = classMapper.selectClassIdByCourseManageId(courseManageId);
        Integer totalClasses = classIdList.size();

        // 用于存储每个 classId 对应的平均签到率（格式化后保留一位小数）
        Map<Long, String> classIdToAverageRateMap = new HashMap<>();

        // 遍历每个 classId
        for (Long classId : classIdList) {
            // 获取该 classId 下的所有 signId
            List<Long> signIdList = signMapper.selectSignIdsByClassId(classId);

            // 用于存储该 classId 下的所有有效签到率
            List<Double> validSignInRates = new ArrayList<>();

            // 遍历每个 signId，获取签到率
            for (Long signId : signIdList) {
                Map<String, Object> signStatus = getSignStatus(signId);
                String signInRateStr = (String) signStatus.get("signInRate");
                double signInRate = Double.parseDouble(signInRateStr);

                // 如果签到率大于0，则计入有效签到率列表
                if (signInRate > 0) {
                    validSignInRates.add(signInRate);
                }
            }

            // 计算该 classId 的平均签到率
            double averageRate = 0;
            if (!validSignInRates.isEmpty()) {
                averageRate = validSignInRates.stream().mapToDouble(Double::doubleValue).average().orElse(0);
            } else if (signIdList.size() == 1) {
                // 如果只有一次签到且签到率为0，则记为零
                averageRate = 0;
            }

            // 将平均签到率格式化为保留一位小数
            String formattedAverageRate = String.format("%.1f", averageRate);

            // 将 classId 和对应的格式化后的平均签到率存入 map
            classIdToAverageRateMap.put(classId, formattedAverageRate);
        }

        // 按 classId 从小到大排序
        List<Map.Entry<Long, String>> sortedEntries = new ArrayList<>(classIdToAverageRateMap.entrySet());
        sortedEntries.sort(Map.Entry.comparingByKey()); // 按 classId 排序

        // 将排序后的结果存入一个新的 Map（如果需要保持顺序，可以使用 LinkedHashMap）
        Map<Long, String> sortedClassIdToAverageRateMap = new LinkedHashMap<>();
        for (Map.Entry<Long, String> entry : sortedEntries) {
            sortedClassIdToAverageRateMap.put(entry.getKey(), entry.getValue());
        }

        // 计算整个课程的平均签到率
        double overallAverageRate = sortedClassIdToAverageRateMap.values().stream()
                .mapToDouble(Double::parseDouble) // 将格式化后的字符串转换回 double
                .average()
                .orElse(0);

        // 将整个课程的平均签到率格式化为保留一位小数
        String formattedOverallAverageRate = String.format("%.1f", overallAverageRate);

        // 构建返回结果
        Map<String, Object> result = new HashMap<>();
        result.put("totalClasses", totalClasses);
        result.put("classIdToAverageRateMap", sortedClassIdToAverageRateMap); // 使用排序后的 Map
        result.put("overallAverageRate", formattedOverallAverageRate); // 格式化后的整体平均签到率

        return result;
    }

    @Override
    public Integer getLatestSignId() {
        return signMapper.getlatestSignId();
    }

    @Override
    public Map<String, Long> getStudentAllSign(Long courseManageId, Long userId) {

        List<Long> classIdList = classMapper.selectClassIdByCourseManageId(courseManageId);
        long totalSign = 0;
        long totalSigned = 0;
        for (Long classId : classIdList) {List<Long> signIdList = signMapper.selectSignIdsByClassId(classId);
           long incremental = signIdList.size();
           totalSign += incremental;
           for (Long signId : signIdList) {
               if (recordMapper.checkSigned(signId, userId) == 1) {
                   totalSigned++;
               }
           }
        }
        logger.info("该课程总共发起签到次数：{}", totalSign);
        logger.info("该学生总共签到次数：{}", totalSigned);
        Map<String, Long> result = new HashMap<>();
        result.put("totalSign",totalSign );
        result.put("totalSigned", totalSigned);
        return result;
    }


}